作者:霞慧水灵灵_973 | 来源:互联网 | 2023-10-12 10:37
篇首语:本文由编程笔记#小编为大家整理,主要介绍了Android架构组件之ViewModel相关的知识,希望对你有一定的参考价值。ViewModel概念及用途
篇首语:本文由编程笔记#小编为大家整理,主要介绍了Android架构组件之ViewModel相关的知识,希望对你有一定的参考价值。
ViewModel概念及用途
ViewModel用来存储和管理UI相关的数据,可于将一个Activity或Fragment组件相关的数据逻辑抽象出来,并能适配组件的生命周期,如当屏幕旋转Activity重建后,ViewModel中的数据依然有效。
引入ViewModel之前,存在如下几个问题:
- 通常android系统来管理UI controllers(如Activity、Fragment)的生命周期,由系统响应用户交互或者重建组件,用户无法操控。当组件被销毁并重建后,原来组件相关的数据也会丢失,如果数据类型比较简单,同时数据量也不大,可以通过
onSaveInstanceState()
存储数据,组件重建之后通过onCreate()
,从中读取Bundle恢复数据。但如果是大量数据,不方便序列化及反序列化,则上述方法将不适用。 - UI controllers经常会发送很多异步请求,有可能会出现UI组件已销毁,而请求还未返回的情况,因此UI controllers需要做额外的工作以防止内存泄露。
- 当Activity因为配置变化而销毁重建时,一般数据会重新请求,其实这是一种浪费,最好就是能够保留上次的数据。
- UI controllers其实只需要负责展示UI数据、响应用户交互和系统交互即可。但往往开发者会在Activity或Fragment中写许多数据请求和处理的工作,造成UI controllers类代码膨胀,也会导致单元测试难以进行。我们应该遵循职责分离原则,将数据相关的事情从UI controllers中分离出来。
上述几个痛点正是ViewModel出现的原因。
ViewModel使用方式
Android架构组件提供了一个ViewModel帮助类来为UI controllers负责数据相关的工作,当配置变化组件销毁重建时,这些数据仍然可以保留。当新的组件重建后,可以立即使用之前保留的数据。下面的示例代码维护了一个User列表数据:
public class MyViewModel extends ViewModel
private MutableLiveData<List<User>> users;
public LiveData<List<User>> getUsers()
if (users &#61;&#61; null)
users &#61; new MutableLiveData<List<Users>>();
loadUsers();
return users;
private void loadUsers()
在Activity中可以按如下方式使用ViewModel&#xff1a;
public class MyActivity extends AppCompatActivity
public void onCreate(Bundle savedInstanceState)
MyViewModel model &#61; ViewModelProviders.of(this).get(MyViewModel.class);
model.getUsers().observe(this, users ->
);
如果Activity销毁重建&#xff0c;可以立即得到一个相同的MyViewModel
实例&#xff0c;它是由之前销毁的Activity创建的。当宿主Activity最终销毁后&#xff0c;系统会调用ViewModel的onCleared()
方法来释放资源。
由上面的例子可以知道&#xff0c;ViewModel的生命周期比特定view
或LifecycleOwner
&#xff08;如Activity实现了LifecycleOwner
接口&#xff09;要长&#xff0c;因此ViewModel不要引用view
、Lifecycle
或其他引用到Activity上下文的对象。
ViewModel
中可以包含LifecycleObserver
&#xff0c;如LiveData
对象。如果ViewModel
需要使用Application
的上下文对象&#xff0c;则可以通过继承AndroidViewModel
&#xff0c;并提供一个以Application为参数的构造函数。
ViewModel的生命周期
ViewModel的生命周期依赖于对应的Activity或Fragment的生命周期。通常会在Activity第一次onCreate()
时创建ViewModel&#xff0c;ViewModel的生命周期一直持续到Activity最终销毁或Frament最终detached&#xff0c;期间由于屏幕旋转等配置变化引起的Activity销毁重建并不会导致ViewModel重建。借用官方示意图来解释一下&#xff1a;
上图左侧为Activity的生命周期过程&#xff0c;期间有一个旋转屏幕的操作&#xff1b;右侧则为ViewModel的生命周期过程。
一般通过如下代码初始化ViewModel&#xff1a;
viewModel &#61; ViewModelProviders.of(this).get(UserProfileViewModel.class);
this
参数一般为Activity或Fragment&#xff0c;因此ViewModelProvider
可以获取组件的生命周期。
Activity在生命周期中可能会触发多次onCreate()
&#xff0c;而ViewModel则只会在第一次onCreate()
时创建&#xff0c;然后直到最后Activity销毁。
Fragment之间分享数据
日常开发中&#xff0c;一个Activity中可能会有多个Fragment&#xff0c;且他们需要进行交互。例如一个Fragment展示列表&#xff0c;另一个Fragment展示选中列表对应的详情信息&#xff0c;之前我们可能会利用宿主Activity并定义几个接口来实现Fragment之间的交互&#xff0c;另外还得考虑Fragment是否已经创建或显示的问题。
上述痛点&#xff0c;可以使用ViewModel来解决&#xff0c;在Fragment之间可以共享ViewModel。示例代码如下&#xff1a;
public class SharedViewModel extends ViewModel
private final MutableLiveData<Item> selected &#61; new MutableLiveData<Item>();
public void select(Item item)
selected.setValue(item);
public LiveData<Item> getSelected()
return selected;
public class MasterFragment extends Fragment
private SharedViewModel model;
public void onCreate(Bundle savedInstanceState)
super.onCreate(savedInstanceState);
model &#61; ViewModelProviders.of(getActivity()).get(SharedViewModel.class);
itemSelector.setOnClickListener(item ->
model.select(item);
);
public class DetailFragment extends Fragment
public void onCreate(Bundle savedInstanceState)
super.onCreate(savedInstanceState);
SharedViewModel model &#61; ViewModelProviders.of(getActivity()).get(SharedViewModel.class);
model.getSelected().observe(this, item ->
);
注意到上面两个Fragment都用到了如下代码来获取ViewModel&#xff1a;
SharedViewModel model &#61; ViewModelProviders.of(getActivity()).get(SharedViewModel.class);
getActivity()
返回的是同一个宿主Activity&#xff0c;因此两个Fragment之间返回的是同一个SharedViewModel
对象。
Fragment间共享ViewModel的优点有&#xff1a;
- 宿主Activity不需要做任何事情&#xff0c;也不需要关心Fragment间交互的内容。
- Fragment只需要了解ViewModel的实现&#xff0c;而无需了解通信目标Fragment。即使一个Fragment已经销毁了&#xff0c;另一个Fragment也能正常工作。
- 每一个Fragment有自己的生命周期&#xff0c;并不受其他Fragment影响。
- Fragment之间解耦。
总结
- ViewModel职责是为Activity或Fragment管理、请求数据&#xff0c;当然具体数据请求逻辑不应该写在ViewModel中&#xff0c;否则ViewModel的职责会变得太重&#xff0c;此处需要一个引入一个Repository&#xff0c;负责数据请求相关工作。具体请参考 Android架构组件。
- ViewModel可以用于Activity内不同Fragment的交互&#xff0c;也可以用作Fragment之间一种解耦方式。
- ViewModel也可以负责处理部分Activity/Fragment与应用其他模块的交互。
- ViewModel生命周期&#xff08;以Activity为例&#xff09;起始于Activity第一次
onCreate()
&#xff0c;结束于Activity最终finish时。
参考&#xff1a;
https://developer.android.google.cn/topic/libraries/architecture/viewmodel.html
我的微信公众号「不混青年」&#xff0c;id「buhunqingnian」&#xff0c;技术之外的分享&#xff1a;